home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 7
/
Apprentice-Release7.iso
/
Environments
/
PowerFantasm™ 4.19a
/
PowerFantasm™
/
F4_EXAMPLES
/
game
/
**README**Game
next >
Wrap
Text File
|
1997-02-10
|
13KB
|
246 lines
In the unregistered version of PowerFantasm, source code for this is not included for
two reasons.
1. The demo can't assemble it because of a code size limitation, and
2. We have to keep the unregistered version size down to a minimum.
You may obtain the source code from our WWW pages - http://www.tau.it/lightsoft
----------------------------------------------------------------------------------
PF410 was to be released with no new example code. Then a few days back I was given
a challenge. These are the notes from that challenge.
The challenge was to write the basics of a native sprite based game in 24 hours and this
is the result.
It starts off 7 hours in, as the first seven hours were writing the basic screen splat
and routines.
Big note for splats - a read or write
to memory with the floating double instructions will cause a memory exception on
604's, so make sure you are 8 aligned if using these instructions - see the screen
splat and init code for usage...
Another note - in this particular example the MMU was letting me get away with passing a
really bad address to clear_icl8 until I switched VM on - then the machine crashed.
Be very sure to check both with VM on and off as the MMU behaves differently.
-------------------------------------------------------------------------------
Ok, 7 hours in and I'm working on the player bullets. Have defined four arrays,
each 10 halfs each. x,y,old_x and old_y for each bullet.
The theory is that when we press the mouse button, the y_array is searched for an empty slot
- that is any slot containing -1. We store x and y coords of the left gun in these arrays.
Calc_bullets steps through the y array looking for entries that are not -1. These are
valid y coords. The y coord is decremented by 10, then checked against 20.
If greater than 20 then do the next bullet slot. If less than 20 then delete the bullet
and set this y_coord to -1.
This set up limits the number of player bullets on screen to 10 (in the equates file).
Because the gun will
auto repeat, after firing a bullet we set a delay so that the fire routine isn't checked
again until this counter runs out.
Next, get it to fire two bullets at the same time - one from each gun. I think that this is
simply a case of altering the coords when we fire and saving it in the next x and y
slot.
Well, aparently not! The first bullet comes out of the left hand gun as it should, but the
other comes out of the bottom of the screen displaced left by some 200 pixels! Eh?
Turns out to just have been bad maths - however, I did think it be a good idea to have the
guns alternate, left/right so reduced the fire delay to 4 cycles and introduced a variable - turret?
which makes the routine alternate left/right guns (which will make for better sound!)
Ok, now I've added an equates file to the project, and redefined the number of bullets to
20. I noticed that the bullets routines were not working right, in that after the max number
had been fired, the guns would not fire until the last bullet cleared the screen. This
was traced to the compare to -1 conditional branch in find_slot being the wrong way
round - should've been a beq!
Noticed that the players ship is slightly blanking out the bullets in the first frame of
bullet movement on the right hand size. This is because I'm simply clearing the whole
32 bits width befoire drawing a bullet, when in fact I only need to clear the bullet width
which is three. So, by moving the bullet over to the far left of the icl8 and
changing clear and print icl8_little, I'll gain speed and remove the visual interference.
Ok, so modified both clear and print - what I did to make sure it was working properly was
change the background colour of the bullet from zero to 1, so I could see how much was being
printed. Also the sprite has been reduced to three pixels wide as it looks better, and
the print adjusted accordingly
Ok, it's midnight, which is 8 hours in. The players bullets are now finished.
Now, onto the nasties. I have to decide on the maximum on screen any any one time.
For now I'll say 20. Each monster is one single icl8, so we need 4 arrays again,
x,y,old_x and old_y - each sized to number_monsters.
We need three routines. One to init the positions. One to calculate positions, and one to
draw the little blighters (erasing the old ones first obviously) It's important, as the
monsters can cross each other, to erase all of them in one go.
To be honest, at this stage, I'll be happy just to draw them and get a frame timing, then
adjust the maximum number accordingly.
So, first to init monsters. As this is a simple game, for now I'm just using one monster
shape - icl8 140. Read into monster_sprite1
I'm going to use fixed data, in init to initialise the arrays. Because i~ have to
type in the data, for now I've set the number of monsters to 5. The init routine
simply copies the x and y coords out of the data to the x,y,x_old and y_old arrays.
Get some coffee.
Ok, it 0025 now, and the init routine is done. Next draw_monsters. First this has to
go through the arrays and call blank_icl8 which will erase all the old monsters.
Then again, go through a loop, anloy this time call draw_icl8 which is already written.
Ok, I've written the clear and splat routines for the monsters, now before running them
I need to get a timing for 1000 frames then I can see how much the monster print has slowed
it down.
Without the stars or monsters I get 532 ticks, which is 1000/(532/60) 113 frames/sec.
Now switch on the monster print...and...589 ticks - thats with 5 monsters=101 fps.
However, what the monster print routine is printing isn't how it looks in Resedit!
So, hello Macsbug...As it turns out, didn't need Macsbug, it's just that splat_icl8
doens't preserve the pointer to the data, so I just saved it in r25 and all is ok.
BUT I did notice that the splat_icl8_three_vert routine seems to be splatting 64
rather than 32 bytes horizontally...yup, it was the clear routines rather than the
splat routines - a hangover from the integer unit word splat.
SO, finally, I can get a time with the stars and five monsters - 102 fps.
Now lets bung up the number of monsters to 10 - 93 fps, now lets see if I cant get
that up by 1. Apparently not at this stage. OK. Well it's 0100, so thats 9 hours.
Next up is the monster movement routines. As I only have 15 hours left, it's has to be
simple this time. I think first I'll write a default controller which just flaots
the monsters about - if they hit a side, then reverse the delta in that direction.
So, we need two more arrays - mdelta_x and mdelta_y (as bytes) BUT at this time, I know
that I'm going to use more than one control mechanism, so I'll define another array
(of bytes) - mcontrol.
In the init phase, we generate random delta values for the monsters - minimum of 1 and
maximum of 3, but this isn't called in the normal init, as we want to call this routine
to start a new stage, so I'll define a new source file - wave_init.s
Ok, written a routine -wave_init which sets up the arrays with random delta values,
in the range of 0-3. This means it's possible to get monsters that wont move, but I'll
sort that out later. (add 1 if zero etc)
Next routine is move_monsters. This gets each monsters x,y and delta_x,y.
Checks the coords of each monster, and if out of bounds, reverses the relevant
delta. Took twenty minutes to write and now the game crashes brilliantly!
Hmm, ok, this was a classic mistake. The x and y's are half sized arrays, the deltas
are bytes - I was simply adding just 1 to the x and y array pointers, so the first x was
correct, all the rest were rubbish! Now, all the monsters are simply moving to the
corners and staying there, which would really make the game too easy :-)
Coffee...
Ok, two faults. Firstly I wasn't saving the delta values back in the array, and
secondly because we are using signed delta values, I needed to extend the sign of
the delta byte! Ok, so it now works! As predicted one of the monsters didn't move
so back into wave init... It turns out that monster #10 is not moving?
Into Macsbug, check out the delta arrays and sure enough, entry 10 is 0?
Bummer - wave_init was stuffing both deltas into the same array! Fixed now and all my
little aliens are moving - hurrah!
Lets get a frame rate...94fps.
Phew. Right is 1:45, which means this is nearly 10 hours in so far.
Next up is player bullets hitting the nasty aliens. Now when an alien is hit, all we
have to do is set its y coord to -1 and modify the routines to ignore such a beasty.
First though, we need to go back into calc_bullets to detect a hit. In calc_b_loop
we subtract 10 from the bullets y coord. Given this coord we can call check_monster_hit
which compares the bullets x and y coords with all active aliens. If the bullet is in one
of the aliens rectangles, it returns the monster number, otherwise zero. This is less
tidy than calling a routine from the main loop, but is faster as we have the bullets coords
and number handy.
Time for some music, as this will take a while to write - eh? This disk is unreadable by...
Oh yes, best put the foreign file access thingies in...
Ok, routines written, and it don't crash, but it isn't working, so I;m going to reduce the
number of monsters to 1 so it's easier to debug.
Doddle - just a mix up over x and y's. In check_monster_hit, if it is, all we do is
bung a -1 in the monsters y coord and it goes away. Right bung the number of monsters
back upto 20 and give it a blast (ah the joys of equate files).
Ok, something very weird is happening. As I shoot monsters, then game gets slower and
slower? I'm supposed to be equalising now! Yup, I had forgotten to modify the drawing routines
to take account of y values with -1. The reason it was slowing down is because it was
drawing off screen, which is probably not lined up on an 8 byte boundary! Anyway, I've
added a down counter that decrements when a monster is killed, and when zero sets the
global flag end_of_wave to tell the main loop to stop.
Phew. 0300 and looking good. Right lets get a frame check with 10 monsters - 92.7 fps.
And with 20..remembering to make some more entries in the init data...80 fps. So we're
still good for a few number of aliens.
Now, next we come to the aliens dropping bombs on us - we need some rules first.
One alien - one bomb. Now because these monsters have to decide when to drop a bomb,
we do not want to be calling get_random for every monster in every loop - far too slow.
What I'll do is define two more arrays - monster_bomb_counter and monster_bomb_counter_reset.
These are set up in wave_init and when the counter reaches zero, the monster tries
to drop a bomb. If it has no active bomb then it can drop one. We reset the counter
from the reset array. This way, all we have to do is decrement a counter - far faster.
An inactive bomb is indicated by -1 in the monster_bomb_y array.
Right, lets do it...First off, wave_init to set up the counter arrays. Ok minor change,
another array - monster_bomb_deltas - the y delta for the bomb - set in init_wave.
Ok, after an hour and half of mucking about tweaking things, that now works. Main problem
was making sure dead aliens don't drop bombs!
Next is the player/alien bomb collision detection. This fits naturally into the move monster
nomb routine at label check_player.
Finally is alien/player collision - again same stuff - draw a rectangle and compare, but
this time we have to check all four corners of the monster against the players rectangle.
Done in draw_m_loop.
OK, its 0630 - fps check.
20 monsters - 80 frames/sec
10 monsters - 93 fps. Dont seem to have wasted any time on the collision detection. Good.
Now it's time to add some basic levels - simple:
Level 1=5 monsters
level 2=10
level 3=15
level 4=20
Then bonus level which ends scheme 1.
...
So some four hours later, I've added in basic sound, some very simple level increments
and got our artist to draw some simple sprites - the end result you can see for yourself!
----------------------------------------------------
Endispiece...
Well, all that was done about three or four days ago. I have now recovered :-)
I'd like to thank Rob, Claire and James for support.
Not only for this little demo, but for all the stirling work they do otherwise.
Please note that:
1. All code contained in PF410 example game is copyright Lightsoft 96.
2. Some of the clear and splat routines can be optimised further - for example
you may find the odd li instruction in a loop, which can move outside etc.
Feel free to use the ideas contained herein, but please do not simply push this work out
as your own. If you use portions of the game code in your own games, then you are
legally obliged to state that portions of the code are copyright Lightsoft.
Thankyou.
-----------------------------------